﻿using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Airthmetic
{
    /// <summary>
    /// 光栅序列数据结构体
    /// </summary>
    public class PatternData
    {
        /// <summary> 图像 </summary>
        public Mat Image = null;
        /// <summary> 格雷码（1bit）/相移法（8bit） </summary>
        public bool Is1bit = true;
        /// <summary> 图像尺寸 </summary>
        public int ImageWidth = 960;
        /// <summary> 图像尺寸 </summary>
        public int ImageHeight = 540;
        /// <summary>
        /// 获取完整图像
        /// </summary>
        public Mat GetFullImage
        {
            get
            {
                if (Image == null)
                    return null;

                return ImageTool.GetFullImage(Image, ImageWidth, ImageHeight);
            }
        }
        /// <summary>
        /// 图像数据
        /// </summary>
        public PatternData() { }
        /// <summary>
        /// 图像数据
        /// </summary>
        /// <param name="image"></param>
        /// <param name="is1bit"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public PatternData(Mat image, bool is1bit, int width, int height)
        {
            this.Image = image;
            this.Is1bit = is1bit;
            this.ImageWidth = width;
            this.ImageHeight = height;
        }
    }

    /// <summary>
    /// 点位 3D
    /// </summary>
    public class Point_XYZ
    {
        public float X = 0;
        public float Y = 0;
        public float Z = 0;
    }

    /// <summary>
    /// 点位 彩色
    /// </summary>
    public class Point_RGB : Point_XYZ
    {
        public int Red;
        public int Green;
        public int Blue;
    }

    /// <summary>
    /// 点位 灰色
    /// </summary>
    public class Point_Gray : Point_XYZ
    {
        public int Gray;
    }

    /// <summary>
    /// 点位 KD树
    /// </summary>
    public class Point_KDTree : Point_RGB
    {
        public double tick;
    }

    #region KD树
    /// <summary>
    /// 增强版KD树实现
    /// </summary>
    internal class KDTree3D
    {
        /// <summary> 当前节点 </summary>
        private KDTreeNode root;

        /// <summary>
        /// 批量构建平衡树方法
        /// </summary>
        /// <param name="points"></param>
        public void BuildBalanced(Point_KDTree[] points)
        {
            root = BuildRecursive(points.ToList(), 0);
        }
        /// <summary>
        /// 获取根
        /// </summary>
        /// <returns></returns>
        public KDTreeNode GetRoot()
        {
            return root;
        }
        /// <summary>
        /// 获取对应深度
        /// </summary>
        /// <param name="depth"></param>
        /// <returns></returns>
        public List<KDTreeNode> GetDepth(int depth)
        {
            List<KDTreeNode> temp = new List<KDTreeNode>();
            GetDepth(root, ref temp, depth);
            return temp;
        }
        /// <summary>
        /// 获取对应深度
        /// </summary>
        /// <param name="nowTree"></param>
        /// <param name="kDTreeNodes"></param>
        /// <param name="depth"></param>
        private void GetDepth(KDTreeNode nowTree, ref List<KDTreeNode> kDTreeNodes, int depth)
        {
            if (nowTree.SplitAxis == depth)
                kDTreeNodes.Add(nowTree);
            if (nowTree.SplitAxis < depth && nowTree.Left != null)
                GetDepth(nowTree.Left, ref kDTreeNodes, depth);
            if (nowTree.SplitAxis < depth && nowTree.Right != null)
                GetDepth(nowTree.Right, ref kDTreeNodes, depth);
        }
        /// <summary>
        /// 批量构建平衡树方法
        /// </summary>
        /// <param name="points"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        private KDTreeNode BuildRecursive(List<Point_KDTree> points, int depth)
        {
            if (points == null || !points.Any())
                return null;

            // 按当前分割轴排序
            var sorted = points.OrderBy(p => p.tick).ToList();

            // 获取中位数索引
            int median = sorted.Count / 2;

            // 创建节点
            var node = new KDTreeNode(sorted[median], depth);

            // 递归构建子树
            node.Left = BuildRecursive(sorted.Take(median).ToList(), depth + 1);
            node.Right = BuildRecursive(sorted.Skip(median + 1).ToList(), depth + 1);

            return node;
        }

        /// <summary>
        /// 节点结构体
        /// </summary>
        public class KDTreeNode
        {
            /// <summary> 点位数据 </summary>
            public Point_KDTree Point_KDTree { get; set; }
            /// <summary> 左节点 </summary>
            public KDTreeNode Left { get; set; }
            /// <summary> 右节点 </summary>
            public KDTreeNode Right { get; set; }
            /// <summary> 第几层，0层最高 </summary>
            public int SplitAxis { get; }

            /// <summary>
            /// 构建节点结构体
            /// </summary>
            /// <param name="point"></param>
            /// <param name="axis"></param>
            public KDTreeNode(Point_KDTree point, int axis)
            {
                Point_KDTree = point;
                SplitAxis = axis;
            }

            /// <summary>
            /// 获取节点信息
            /// </summary>
            public string GetMessage { get { return $"[{SplitAxis}] ({Point_KDTree.X}, {Point_KDTree.Y}, {Point_KDTree.Z})"; } }
        }
    }
    #endregion
}
